﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Xml;
using ValuationResource;

namespace ValuationLogic
{
    public class Logic
    {
        private static String Url = "http://www.cmegroup.com/CmeWS/da/DailySettlement/V1/DSReport/ProductCode/CL/FOI/FUT/EXCHANGE/XNYM/Underlying/CL/ProductId/425";

        
        private static DateTime lastRefreshDate = new DateTime(9999, 2, 14);
        private static EventWaitHandle refreshLck = new EventWaitHandle(false, EventResetMode.AutoReset);

        public static bool refreshDone = false;

        public static void StartForRefreshData(Thread refreshData_thread)
        {
            refreshData_thread = new Thread(new ThreadStart(RefreshingData));
            refreshData_thread.Start();
        }

        public static bool addUser(User user)
        {
            // TODO 
            // Model.addUser(user);
            // *****************
            return true;
        }

        public static bool checkUser(User user)
        {
            // TODO
            // Model.checkUser(user);
            return true;
        }

        public static bool addSwap(Swap swap)
        {
            swap.calRiskExposure(curDate);
            // TO BE DONE
            // Model.addSwap(swap);
            // ***************************
            return true;
        }

        public static List<Swap> getSwaps(String ID)
        {
            // TO BE DONE
            // Model.getSwaps(String userName);
            // ***************************
            return null;
        }

        public static bool calSwap(Swap swap)
        {
            if (!(SwapDate.equalsMonthYear(swap.getCalDate(), curDate) && curDate.Day == swap.getCalDate().Day))
            {
                refreshData();
                return swap.calculate(curDate);
            }
            return true;
        }

        /*
        private static double clickPnL(Swap swap)
        {
            // only days changed may cause PnL changing
            if (!(SwapDate.equalsMonthYear(swap.getCalDate(), curDate) && curDate.Day == swap.getCalDate().Day))
            {
                swap.calPnL(curDate);
                // TO BE DONE
                // Model.updateSwap(swap);
                // ***************************
            }
            return swap.getPnL();
        }

        private static double calRiskexposure(Swap swap)
        {
            if (!(SwapDate.equalsDay(swap.getCalDate(), curDate)))
            {
                swap.calRiskExposure(curDate);
            }
            return swap.getRiskExposure();
        }*/

        public static DateTime curDate = DateTime.Now;
        public static void setCurDate(DateTime newDate)
        {
            curDate = newDate;
        }
        public static DateTime getCurDate()
        {
            return curDate;
        }


        private static void savePrice()
        {
            //TODO
            // Model.saveSettlePrice(priceTable);
            // ***********
        }

        private static void restorePrice()
        {
            //TODO
            // priceTable = Model.getSettlePrice();
            // ************
        }



        internal static void refreshData()
        {
            if (SwapDate.equalsDay(lastRefreshDate, getInternetTime()))
            {
                restorePrice();
                return;
            }
            //wantRefresh = true;
            refreshLck.Set();
        }

        /*internal static void RefreshingData()
        {
            MessageBox.Show("Contract start refresh thread");
            while (true)
            {
                refreshLck.WaitOne();
                XmlDocument doc = new XmlDocument();
                try
                {
                    doc.Load(Url);
                }
                catch (Exception e)
                {
                    MessageBox.Show("Error when Load Url in Contract.cs.\n" + e.ToString());
                    throw e;
                }
                XmlElement root = doc.DocumentElement;
                XmlNodeList nodeList = root.SelectNodes("/dailySettlementList/dsRecordTO");
                if (nodeList != null)
                {
                    foreach (XmlNode monthNode in nodeList)
                    {
                        String contractID = monthNode.SelectSingleNode("contractId").InnerText;
                        String[] stringList = contractID.Split(' ');
                        int contract_month = (int)monthNum[stringList[0]];
                        int contract_year = 2000 + Convert.ToInt32(stringList[1]);
                        double settPrice = Convert.ToDouble(monthNode.SelectSingleNode("sett").InnerText);
                        
                        //System.Windows.MessageBox.Show("contractID:" + (contract_year * 100 + contract_month) + "\nprice:" + settPrice);
                    }
                }

            }
        }*/

        private static void RefreshingData()
        {
            MessageBox.Show("Start refresh thread");
            if (Contract.monthNum.Count == 0)
                Contract.MonthNameToNum();
            while (true)
            {
                refreshDone = false;
                XmlDocument doc = new XmlDocument();

                DateTime today = getInternetTime().AddDays(-1);
                while (today.DayOfWeek.ToString()[0] == 'S')
                    today = today.AddDays(-1);
                doc.Load(Url + "?tradeDate=" + getUrlDate(today));
                while (doc.SelectNodes("/dailySettlementList/dsRecordTO").Count > 0)
                {
                    XmlNodeList nodeList = doc.SelectNodes("/dailySettlementList/dsRecordTO");
                    int min_month = 20, min_year = 9999;
                    double daySettPrice = 0;
                    foreach (XmlNode monthNode in nodeList)
                    {
                        String contractID = monthNode.SelectSingleNode("contractId").InnerText;
                        String[] stringList = contractID.Split(' ');
                        int contract_month = (int)Contract.monthNum[stringList[0]];
                        int contract_year = 2000 + Convert.ToInt32(stringList[1]);
                        double settPrice = Convert.ToDouble(monthNode.SelectSingleNode("sett").InnerText);
                        int dateValue = today.Month * 100000000 + today.Day * 1000000 + (today.Year - 2000) * 10000 + (contract_year - 2000) * 100 + contract_month;
                        Contract.priceTable[dateValue] = settPrice; 
                        if (contract_year < min_year || (contract_year == min_year && contract_month < min_month))
                        {
                            min_year = contract_year;
                            min_month = contract_month;
                            daySettPrice = settPrice;
                        }
                    }
                    Settlement.priceTable[today.Year * 10000 + today.Month * 100 + today.Day] = daySettPrice;
                    //System.Windows.MessageBox.Show(today.Year + "\n" + today.Month + "\n" + today.Day + "\n" + daySettPrice);
                    do
                    {
                        today = today.AddDays(-1);
                    }
                    while (today.DayOfWeek.ToString()[0] == 'S');
                    
                    try
                    {
                        doc.Load(Url + "?tradeDate=" + getUrlDate(today));
                    }
                    catch (Exception e)
                    {
                        MessageBox.Show("Error when Load Url in Settlement.cs.\n" + e.ToString());
                        throw e;
                    }
                }
                lastRefreshDate = getInternetTime();
                savePrice();
                MessageBox.Show("Refresh Data Finished!");
                refreshDone = true;
                refreshLck.WaitOne();
            }
        }



        private static String getUrlDate(DateTime date)
        {
            //06%2F04%2F2013
            String day, month;
            if (date.Day < 10)
                day = '0' + Convert.ToString(date.Day);
            else
                day = Convert.ToString(date.Day);
            if (date.Month < 10)
                month = '0' + Convert.ToString(date.Month);
            else
                month = Convert.ToString(date.Month);
            return month + "%2F" + day + "%2F" + Convert.ToString(date.Year);
        }

        public static DateTime getInternetTime()
        {
            DateTime internet_time = new DateTime();
            //TODO
            // DateTime
            
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://nist.time.gov/timezone.cgi?UTC/s/0");
            request.Method = "GET";
            request.Accept = "text/html, application/xhtml+xml, */*";

            return DateTime.Now;
        }
    }
}
